﻿/*********************************************************************************
 *Author:         OnClick
 *Version:        0.0.2.252
 *UnityVersion:   2018.4.24f1
 *Date:           2021-05-18
 *Description:    IFramework
 *History:        2018.11--
*********************************************************************************/
using System;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace IFramework.AAEX
{

    public abstract class AssetLoader<TObject> : MonoBehaviour
    {
        public enum AssetLoadState
        {
            None,
            Prepare,
            Compelete
        }
        private AssetLoadState _state =  AssetLoadState.None;
        public AssetLoadState state { get { return _state; } }
        private bool _dirty;
        public string path;
        private AsyncOperationHandle<TObject> _handler;
        public AsyncOperationStatus status
        {
            get
            {
                switch (_state)
                {
                    case AssetLoadState.None:
                        return AsyncOperationStatus.None;
                    case AssetLoadState.Prepare:
                    case AssetLoadState.Compelete:
                    default:
                        return _handler.Status;
                }
            }
        }
        public bool isDone {
            get
            {
                switch (_state)
                {
                    case AssetLoadState.None:
                        return false;
                    case AssetLoadState.Prepare:
                    case AssetLoadState.Compelete:
                    default:
                        return _handler.IsDone;
                }
            }
        }
        public float percent
        {
            get
            {
                switch (_state)
                {
                    case AssetLoadState.None:
                        return 0;
                    case AssetLoadState.Prepare:
                    case AssetLoadState.Compelete:
                    default:
                        return _handler.PercentComplete;
                }
            }
        }

        public Exception err
        {
            get
            {
                switch (_state)
                {
                    case AssetLoadState.None: return null;
                    case AssetLoadState.Prepare:
                    case AssetLoadState.Compelete:
                    default:
                        return _handler.OperationException;
                }
            }
        }
        public TObject asset
        {
            get
            {
                switch (_state)
                {
                    case AssetLoadState.None: return default(TObject);
                    case AssetLoadState.Prepare:
                    case AssetLoadState.Compelete:
                    default:
                        return _handler.Result;
                }
            }
        }

        public void SetPath(string path)
        {
            if (this.path == path) return;
            _dirty = true;
            this.path = path;
            Prepare();
        }
        public void Prepare()
        {
            if (_dirty)
            {
                Rlease();
            }
            switch (_state)
            {
                case AssetLoadState.None:
                    if (!string.IsNullOrEmpty(path))
                    {
                        _handler = Assets.Load<TObject>(path);
                        _handler.Completed += _handler_Completed;
                        _state = AssetLoadState.Prepare;
                    }
                    break;
                case AssetLoadState.Prepare:
                    break;
                case AssetLoadState.Compelete:
                    _handler_Completed(_handler);
                    break;
                default:
                    break;
            }
        }
        public void Rlease()
        {
            switch (_state)
            {
                case AssetLoadState.None:
                    break;
                case AssetLoadState.Prepare:
                case AssetLoadState.Compelete:
                default:
                    OnReleaseAsset();
                    _handler.Completed -= _handler_Completed;
                    Assets.Release(_handler);
                    _state = AssetLoadState.None;
                    break;
            }
            _dirty = false;
        }
        private void _handler_Completed(AsyncOperationHandle<TObject> obj)
        {
            if (obj.Status== AsyncOperationStatus.Succeeded)
            {
                OnLoadAssetCompelete(obj.Result);
            }
            else
            {
                throw obj.OperationException;
            }
        }
        protected abstract void OnLoadAssetCompelete(TObject asset);
        protected virtual void OnReleaseAsset() { }
        protected virtual void Start()
        {
            Prepare();
        }
        protected virtual void OnDestroy()
        {
            Rlease();
        }
    }
}
